package com.file.parser;

import com.file.bo.AppTmriJsjl;
import com.file.bo.ResponseData;
import com.file.constant.ErrorCode;
import com.file.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import technology.tabula.*;
import technology.tabula.detectors.SpreadsheetDetectionAlgorithm;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;

import java.io.File;
import java.util.*;

/**
 * 交管12123APP机动车驾驶人安全驾驶记录
 * @author anyspa
 */

@Slf4j
public class AppTmriJsjlPdfParser extends BasePdfParser {

    public ResponseData<String> parseAppTmriJsjlPdfToJson(String daId, String filePath) {
        log.info("parseAppTmriJsjlPdfToJson started, daId:{}", daId);
        String json = null;

        try {
            AppTmriJsjl appTmriJsjl = parseAppTmriJsjlPdf(filePath, daId);
            json = JsonUtils.convertObjectToJson(appTmriJsjl);
        } catch (Exception e) {
            log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseAppTmriJsjlPdfToJson failed", e);
            return new ResponseData<>(json, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
        }

        log.info("parseAppTmriJsjlPdfToJson completed, daId:{}", daId);
        return new ResponseData<>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
    }

    private AppTmriJsjl parseAppTmriJsjlPdf(String filePath, String daId) {
        AppTmriJsjl appTmriJsjl = parseAppTmriJsjlHeader(filePath);

        parseSafeDrivingRecord(appTmriJsjl, filePath, daId);

        return appTmriJsjl;
    }

    private AppTmriJsjl parseAppTmriJsjlHeader(String filePath) {
        AppTmriJsjl appTmriJsjl = new AppTmriJsjl();
        AppTmriJsjl.BasicInfo basicInfo = new AppTmriJsjl.BasicInfo();

        String pdfHeaderText = parsePdfHeaderText(filePath);
        String name = pdfHeaderText.substring(pdfHeaderText.indexOf("驾驶人姓名：") + 6, pdfHeaderText.indexOf("，性别")).trim();
        String sex = pdfHeaderText.substring(pdfHeaderText.indexOf("性别：") + 3, pdfHeaderText.indexOf("，身份证明号码")).trim();
        String idNo = pdfHeaderText.substring(pdfHeaderText.indexOf("身份证明号码：") + 7, pdfHeaderText.indexOf("，初次领证日期")).trim();
        String initialApplicationDate = pdfHeaderText.substring(pdfHeaderText.indexOf("初次领证日期：") + 7,
                pdfHeaderText.indexOf("，当前驾驶准驾车型")).trim();
        String currentQuasiDrivingModel = pdfHeaderText.substring(pdfHeaderText.indexOf("当前驾驶准驾车型：") + 9,
                pdfHeaderText.indexOf("，当前交通违法累积记分")).trim();
        String currentTrafficViolationsAccumulateScore = pdfHeaderText.substring(
                pdfHeaderText.indexOf("当前交通违法累积记分：") + 11, pdfHeaderText.indexOf("。该驾驶人安全驾驶记录")).trim();

        basicInfo.setName(name);
        basicInfo.setSex(sex);
        basicInfo.setIdNo(idNo);
        basicInfo.setInitialApplicationDate(initialApplicationDate);
        basicInfo.setCurrentQuasiDrivingModel(currentQuasiDrivingModel);
        basicInfo.setCurrentTrafficViolationsAccumulateScore(currentTrafficViolationsAccumulateScore);
        appTmriJsjl.setBasicInfo(basicInfo);
        return appTmriJsjl;
    }

    private void parseSafeDrivingRecord(AppTmriJsjl appTmriJsjl, String filePath, String daId) {
        AppTmriJsjl.TrafficViolation trafficViolation = new AppTmriJsjl.TrafficViolation();
        AppTmriJsjl.TrafficAccidentSituation trafficAccidentSituation = new AppTmriJsjl.TrafficAccidentSituation();
        AppTmriJsjl.FullMarkRecord fullMarkRecord = new AppTmriJsjl.FullMarkRecord();
        AppTmriJsjl.QuasiDrivingTypeChangeRecord quasiDrivingTypeChangeRecord = new AppTmriJsjl.QuasiDrivingTypeChangeRecord();
        String pdfText = getPdfTextByStripper2(filePath);

        // 交通违法情况
        String trafficViolationDescription = pdfText.substring(pdfText.indexOf("一、交通违法情况") + 8, pdfText.indexOf("二、交通事故情况"));
        if (trafficViolationDescription.contains("违法时间")) {
            trafficViolationDescription = trafficViolationDescription.substring(0, trafficViolationDescription.indexOf("违法时间"));
        }
        trafficViolation.setTrafficViolationDescription(trafficViolationDescription.trim());

        // 交通事故情况
        String trafficAccidentSituationDescription = pdfText.substring(pdfText.indexOf("二、交通事故情况") + 8,
                pdfText.indexOf("三、满分记录情况"));
        if (trafficAccidentSituationDescription.contains("事故时间")) {
            trafficAccidentSituationDescription = trafficAccidentSituationDescription.substring(0,
                    trafficAccidentSituationDescription.indexOf("事故时间"));
        }
        trafficAccidentSituation.setTrafficAccidentSituationDescription(trafficAccidentSituationDescription.trim());

        // 满分记录情况
        String fullMarkRecordDescription = pdfText.substring(pdfText.indexOf("三、满分记录情况") + 8,
                pdfText.indexOf("四、准驾车型变更记录情况"));
        if (fullMarkRecordDescription.contains("清分日期")) {
            fullMarkRecordDescription = fullMarkRecordDescription.substring(0, fullMarkRecordDescription.indexOf("清分日期"));
        }
        fullMarkRecord.setFullMarkRecordDescription(fullMarkRecordDescription.trim());

        // 准驾车型变更记录情况
        String quasiDrivingTypeChangeRecordDescription = pdfText.substring(pdfText.indexOf("四、准驾车型变更记录情况") + 12,
                pdfText.lastIndexOf("变更记录。") + 5);
        if (quasiDrivingTypeChangeRecordDescription.contains("变更日期")) {
            quasiDrivingTypeChangeRecordDescription = quasiDrivingTypeChangeRecordDescription.substring(0,
                    quasiDrivingTypeChangeRecordDescription.indexOf("变更日期"));
        }
        quasiDrivingTypeChangeRecord.setQuasiDrivingTypeChangeRecordDescription(quasiDrivingTypeChangeRecordDescription.trim());

        appTmriJsjl.setTrafficViolation(trafficViolation);
        appTmriJsjl.setTrafficAccidentSituation(trafficAccidentSituation);
        appTmriJsjl.setFullMarkRecord(fullMarkRecord);
        appTmriJsjl.setQuasiDrivingTypeChangeRecord(quasiDrivingTypeChangeRecord);

        parseSafeDrivingRecordAllTables(appTmriJsjl, filePath, daId);
    }

    private void parseSafeDrivingRecordAllTables(AppTmriJsjl appTmriJsjl, String filePath, String daId) {
        // 1. 读取文件
        File pdf = new File(filePath);

        // 2. pdfbox读取PDDocument
        try (PDDocument pdfDocument = PDDocument.load(pdf)) {

            // 3. tabula新建ObjectExtractor和NurminenDetectionAlgorithm，同时准备接收表格Rectangle的结构
            ObjectExtractor objectExtractor = new ObjectExtractor(pdfDocument);
            // NurminenDetectionAlgorithm detectionAlgorithm = new NurminenDetectionAlgorithm();
            SpreadsheetDetectionAlgorithm sea = new SpreadsheetDetectionAlgorithm();

            Map<Integer, List<Rectangle>> detectedTables = new HashMap<>();

            // 4. 获取每页的PageIterator
            PageIterator pages = objectExtractor.extract();

            // 5. 解析每页的Rectangle(table的位置)
            while (pages.hasNext()) {
                Page page = pages.next();

                List<Rectangle> tablesOnPage = sea.detect(page);
                if (tablesOnPage.size() > 0) {
                    detectedTables.put(page.getPageNumber(), tablesOnPage);
                }
            }

            // 6.通过table位置获取表格具体内容
            SpreadsheetExtractionAlgorithm bea = new SpreadsheetExtractionAlgorithm();

            // 如果单页pdf中有多个表格，则解析出来的List<Rectangle>会有多个对象
            for (Map.Entry<Integer, List<Rectangle>> entry : detectedTables.entrySet()) {
                Page page = objectExtractor.extract(entry.getKey());

                for (int i = 0; i < entry.getValue().size(); i++) {
                    Rectangle rectangle = entry.getValue().get(i);
                    Page area = page.getArea(rectangle);

                    List<Table> tableList = bea.extract(area);
                    for (Table table : tableList) {
                        if (Objects.equals(table.getCell(0, 0).getText(false).trim(), "违法时间")) {
                            parseTrafficViolationRecords(appTmriJsjl, table);
                        } else if (Objects.equals(table.getCell(0, 0).getText(false).trim(), "事故时间")) {
                            parseTrafficAccidentSituationRecords(appTmriJsjl, table);
                        } else if (Objects.equals(table.getCell(0, 0).getText(false).trim(), "清分日期")) {
                            parseFullMarkRecordDetails(appTmriJsjl, table);
                        } else if (Objects.equals(table.getCell(0, 0).getText(false).trim(), "变更日期")) {
                            parseQuasiDrivingTypeChangeRecordDetails(appTmriJsjl, table);
                        }
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void parseTrafficViolationRecords(AppTmriJsjl appTmriJsjl, Table table) {
        List<AppTmriJsjl.TrafficViolationRecord> trafficViolationRecords = new ArrayList<>();
        for (int i = 0; i < table.getRowCount(); i++) {
            if (Objects.equals(table.getCell(i, 0).getText(false).trim(), "违法时间")) {
                continue;
            }
            AppTmriJsjl.TrafficViolationRecord trafficViolationRecord = new AppTmriJsjl.TrafficViolationRecord();
            trafficViolationRecord.setViolationTime(table.getCell(i, 0).getText(false));
            trafficViolationRecord.setViolationPlace(table.getCell(i, 1).getText(false));
            trafficViolationRecord.setViolationBehavior(table.getCell(i, 2).getText(false));
            trafficViolationRecord.setViolationType(table.getCell(i, 3).getText(false));
            trafficViolationRecord.setRecordPoints(table.getCell(i, 4).getText(false));
            trafficViolationRecord.setPenaltyAmount(table.getCell(i, 5).getText(false));
            trafficViolationRecord.setPunishmentType(table.getCell(i, 6).getText(false));
            trafficViolationRecord.setPaymentMark(table.getCell(i, 7).getText(false));

            trafficViolationRecords.add(trafficViolationRecord);
        }
        appTmriJsjl.getTrafficViolation().setTrafficViolationRecords(trafficViolationRecords);
    }

    private void parseTrafficAccidentSituationRecords(AppTmriJsjl appTmriJsjl, Table table) {
        List<AppTmriJsjl.TrafficAccidentSituationRecord> trafficAccidentSituationRecords = new ArrayList<>();
        for (int i = 0; i < table.getRowCount(); i++) {
            if (Objects.equals(table.getCell(i, 0).getText(false).trim(), "事故时间")) {
                continue;
            }
            AppTmriJsjl.TrafficAccidentSituationRecord trafficAccidentSituationRecord = new AppTmriJsjl.TrafficAccidentSituationRecord();
            trafficAccidentSituationRecord.setAccidentTime(table.getCell(i, 0).getText(false));
            trafficAccidentSituationRecord.setAccidentLocation(table.getCell(i, 1).getText(false));
            trafficAccidentSituationRecord.setPrincipalWrongfulAct(table.getCell(i, 2).getText(false));
            trafficAccidentSituationRecord.setAccidentType(table.getCell(i, 3).getText(false));
            trafficAccidentSituationRecord.setAccidentLiability(table.getCell(i, 4).getText(false));
            trafficAccidentSituationRecord.setDeathToll(table.getCell(i, 5).getText(false));
            trafficAccidentSituationRecord.setNumberOfInjured(table.getCell(i, 6).getText(false));

            trafficAccidentSituationRecords.add(trafficAccidentSituationRecord);
        }
        appTmriJsjl.getTrafficAccidentSituation().setTrafficAccidentSituationRecords(trafficAccidentSituationRecords);
    }

    private void parseFullMarkRecordDetails(AppTmriJsjl appTmriJsjl, Table table) {
        List<AppTmriJsjl.FullMarkRecordDetail> fullMarkRecordDetails = new ArrayList<>();
        for (int i = 0; i < table.getRowCount(); i++) {
            if (Objects.equals(table.getCell(i, 0).getText(false).trim(), "清分日期")) {
                continue;
            }
            AppTmriJsjl.FullMarkRecordDetail fullMarkRecordDetail = new AppTmriJsjl.FullMarkRecordDetail();
            fullMarkRecordDetail.setClearingDate(table.getCell(i, 0).getText(false));
            fullMarkRecordDetail.setScoringYear(table.getCell(i, 1).getText(false));
            fullMarkRecordDetail.setClearScores(table.getCell(i, 2).getText(false));
            fullMarkRecordDetail.setLicenseIssuePlace(table.getCell(i, 3).getText(false));

            fullMarkRecordDetails.add(fullMarkRecordDetail);
        }
        appTmriJsjl.getFullMarkRecord().setFullMarkRecordDetails(fullMarkRecordDetails);
    }

    private void parseQuasiDrivingTypeChangeRecordDetails(AppTmriJsjl appTmriJsjl, Table table) {
        List<AppTmriJsjl.QuasiDrivingTypeChangeRecordDetail> quasiDrivingTypeChangeRecordDetails = new ArrayList<>();
        for (int i = 0; i < table.getRowCount(); i++) {
            if (Objects.equals(table.getCell(i, 0).getText(false).trim(), "变更日期")) {
                continue;
            }
            AppTmriJsjl.QuasiDrivingTypeChangeRecordDetail quasiDrivingTypeChangeRecordDetail = new AppTmriJsjl.QuasiDrivingTypeChangeRecordDetail();
            quasiDrivingTypeChangeRecordDetail.setChangeDate(table.getCell(i, 0).getText(false));
            quasiDrivingTypeChangeRecordDetail.setOriginalQuasiDrivingModel(table.getCell(i, 1).getText(false));
            quasiDrivingTypeChangeRecordDetail.setNewQuasiDrivingModel(table.getCell(i, 2).getText(false));

            quasiDrivingTypeChangeRecordDetails.add(quasiDrivingTypeChangeRecordDetail);
        }
        appTmriJsjl.getQuasiDrivingTypeChangeRecord().setQuasiDrivingTypeChangeRecordDetails(quasiDrivingTypeChangeRecordDetails);
    }

//    public static void main(String[] args) {
//        AppTmriJsjlPdfParser appTmriJsjlPdfParser = new AppTmriJsjlPdfParser();
//        String json = appTmriJsjlPdfParser.parseAppTmriJsjlPdfToJson("", "D:\\data\\file\\appTmriJsjl\\驾驶记录.pdf").getData();
//        System.out.println(json);
//
//        json = appTmriJsjlPdfParser.parseAppTmriJsjlPdfToJson("", "D:\\data\\file\\appTmriJsjl\\app-tmri-jsjl_aqjsjl.pdf").getData();
//        System.out.println(json);
//    }
}